/***********************************************************
File name     : xfile.c
Author name   : lancz
Email address : chengzhang.lan@jointlighting.com
Create time   : 2022-09-07 16:09:38
***********************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "rtdef.h"
#ifdef __linux__
#include <libgen.h>
#include <sys/stat.h>
#include <sys/types.h>
#elif defined(RT_USED)
#include <dfs_posix.h>
#endif

#include "xstddef.h"
#define MAXPATHLEN 256

xt_s32 XfileIsExists(xt_rostring path) {
#ifdef __linux__
    if (access(path, F_OK) != -1) {
        return XTRUE;
    } else {
        return XFALSE;
    }
#elif defined(RT_USED)
	struct stat buf = {0};
	return stat(path, &buf);
#endif
}

char *dirname(const char *path)
{
	static char bname[MAXPATHLEN];
	register const char *endp;

	/* Empty or NULL string gets treated as "." */
	if (path == NULL || *path == '\0') {
		(void)strcpy(bname, ".");
		return(bname);
	}

	/* Strip trailing slashes */
	endp = path + strlen(path) - 1;
	while (endp > path && *endp == '/')
		endp--;

	/* Find the start of the dir */
	while (endp > path && *endp != '/')
		endp--;

	/* Either the dir is "/" or there are no slashes */
	if (endp == path) {
		(void)strcpy(bname, *endp == '/' ? "/" : ".");
		return(bname);
	} else {
		do {
			endp--;
		} while (endp > path && *endp == '/');
	}

	if (endp - path + 1 > sizeof(bname)) {
		errno = ENAMETOOLONG;
		return(NULL);
	}
	(void)strncpy(bname, path, endp - path + 1);
	bname[endp - path + 1] = '\0';
	return(bname);
}

xt_s32 Xmkdir(const char *dir) 
{
    size_t len = 0;
    xt_s8 *p = NULL;
    xt_s8 tmp[256] = {0};

    len = snprintf(tmp, sizeof(tmp), "%s", dir);
    if (tmp[len - 1] == '/') {
        tmp[len - 1] = 0;
    }

    for (p = tmp + 1; *p; p++) {
        if (*p == '/') {
            *p = 0;
            mkdir(tmp, S_IRWXU);
            *p = '/';
        }
    }
    return mkdir(tmp, S_IRWXU);
}

xt_s32 XfileWrite(xt_rostring path, void *data, xt_s32 size) {
    if (NULL == path || NULL == data)
        return XERROR_FUNC_ARGS;

    xt_string dupdir = strdup(path);
    xt_string dir = dirname(dupdir);
    Xmkdir(dir);
    free(dupdir);

    FILE *fp = fopen(path, "w");
    if (NULL == fp)
        return XERROR;

    xt_s32 ret = fwrite(data, sizeof(xt_s8), size, fp);
    fclose(fp);
    return ret;
}

xt_s32 XfileRead(xt_rostring path, void *buf, xt_s32 size) {
    if (NULL == path || NULL == buf)
        return XERROR_FUNC_ARGS;

    if (XfileIsExists(path))
        return XERROR;

    FILE *fp = fopen(path, "r");
    if (NULL == fp)
        return XERROR;

    xt_s32 ret = fread(buf, sizeof(xt_s8), size, fp);
    fclose(fp);
    return ret;
}

xt_s32 XfileRemove(xt_rostring path) {
    remove(path);
    return XOK;
}

xt_s32 XfileSize(xt_rostring path) {
    struct stat buf = {0};
    xt_s32 ret = stat(path, &buf);
    if (0 != ret)
        return ret;

    return buf.st_size;
}

#if defined(__linux__)
xt_string XfileTemp(xt_string prefix, xt_s32 buf_size) {
    if (NULL == prefix)
        return NULL;

    snprintf(prefix + strlen(prefix), buf_size, "XXXXXX");
    mkstemp(prefix);
    return prefix;
}


xt_string XfileBasename(xt_rostring path, xt_string buf, xt_s32 size) {
    if (NULL == path)
        return NULL;

    snprintf(buf, size, "%s", path);
    return basename(buf);
}

#endif

xt_string XfileDirname(xt_rostring path, xt_string buf, xt_s32 size) {
    if (NULL == path)
        return NULL;

    return dirname((xt_s8 *)path);
}

xt_s32 XfileMove(xt_rostring src, xt_rostring dst) {
    if (!src || !dst)
        return XERROR_FUNC_ARGS;

    xt_s32 len = strlen(src) + strlen(dst) + 10;
    xt_string cmd = (xt_string)malloc(len);
    if (!cmd)
        return XERROR_MEM;

    snprintf(cmd, len, "mv %s %s", src, dst);
    system(cmd);

    free(cmd);
    return XOK;
}
